package fx.sample;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import fx.utils.EncryptUtil;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Home {
    public RadioButton decode;
    public RadioButton encode;
    public Label text1;
    public Label text2;
    public TextField sign;
    public TextField secret;
    public Button submit;
    public TextArea out;
    public RadioButton SM;
    public RadioButton AES;
    public RadioButton sdk;
    public RadioButton web;
    public TextArea in;
    public Label text4;
    public CheckBox isSign;
    public TextField signResult;
    public Label signTitle;
    static String split = "|";

    public static String tmpFile = SystemUtil.getUserInfo().getTempDir() + "fx\\history.txt";
    String[] key = new String[]{"no", "type", "secret", "sign", "in", "out", "time"};

    public void format(ActionEvent actionEvent) {
        String text = out.getText();
        JSONObject json = null;
        try {
            json = JSON.parseObject(text);

        } catch (Exception e) {
            try {
                json = JSON.parseObject(text);
            } catch (Exception e1) {
                return;
            }

        }
        String pretty = JSON.toJSONString(json, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat);
        out.setText(pretty);
    }

    public void privateCert(ActionEvent actionEvent) throws IOException {
        GridPane root = FXMLLoader.load(getClass().getResource("project.fxml"));
        Node item1 = root.lookup("#item1");
        Node item2 = root.lookup("#item2");
        Node item3 = root.lookup("#item3");
        item1.setAccessibleText("2");
        item2.setVisible(false);
        item3.setVisible(false);
        Scene scene = new Scene(root, -1, -1);
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.setScene(scene);
        stage.show();
    }

    public void privateDataBase(ActionEvent actionEvent) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("project.fxml"));
        Node item1 = root.lookup("#item1");
        Node item2 = root.lookup("#item2");
        Node item3 = root.lookup("#item3");
        item1.setAccessibleText("3");
        item2.setVisible(false);
        item3.setVisible(false);
        Scene scene = new Scene(root, -1, -1);
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.setScene(scene);
        stage.show();
    }

    private static void handle(TableColumn.CellEditEvent<Map, String> t) {

    }

    public void showHistory(ActionEvent actionEvent) throws IOException {
        TableView table = new TableView(generateDataInMap());
        Parent root = FXMLLoader.load(getClass().getResource("history.fxml"));
        Stage stage = new Stage();
        stage.setTitle("历史记录");
        table.setEditable(true);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        List<TableColumn> tittle = Arrays.asList(new TableColumn[]{new TableColumn("序号"), new TableColumn("类型"), new TableColumn("秘钥"), new TableColumn("签名秘钥"), new TableColumn("输入"), new TableColumn("输出"), new TableColumn("时间")});
        table.getColumns().addAll(tittle);
        for (int i = 0; i < key.length; i++) {
            tittle.get(i).setCellFactory(TextFieldTableCell.forTableColumn());//给需要编辑的列设置属性
            tittle.get(i).setCellValueFactory(new MapValueFactory(key[i]));
        }
        final VBox vbox = new VBox();
        vbox.setPrefWidth(995);
        vbox.setPadding(new Insets(2, 0, 0, 5));
        vbox.getChildren().addAll(table);
        Scene scene = new Scene(root, -1, -1);
        Node lookup = root.lookup("#pane");
        Pane p = (Pane) lookup;
        p.getChildren().add(vbox);
        stage.setResizable(false);
        stage.setScene(scene);
        stage.show();
    }

    private ObservableList<Map> generateDataInMap() {
        ObservableList<Map> allData = FXCollections.observableArrayList();
        try {
            List<String> list = FileUtil.readLines(FileUtil.file(tmpFile), Charset.defaultCharset());
            for (int i = 0; i < list.size(); i++) {
                String tmp = list.get(i);
                if (StringUtils.isNotEmpty(tmp)) {
                    String[] split = tmp.split("\\|");
                    Map<String, String> dataRow = new HashMap<>();
                    dataRow.put("no", i + 1 + "");
                    for (int j = 1; j < key.length; j++) {
                        dataRow.put(key[j], split[j - 1]);
                    }

                    allData.add(dataRow);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return allData;
    }

    public void encodeType(ActionEvent actionEvent) {
        if (actionEvent.getSource().equals(decode)) {
            text1.setText("待解密内容");
            text2.setText("解密结果");
            isSign.setText("是否验签");
            text4.setText("验签结果");
        }
        if (actionEvent.getSource().equals(encode)) {
            text1.setText("待加密内容");
            text2.setText("加密结果");
            isSign.setText("是否加签");
            text4.setText("加签结果");
        }
        if (actionEvent.getSource().equals(web)) {
            secret.setText("5278MMN5412365UH");
            sign.setText("ITL87v5ik7*=()55ilpp751O");
            SM.setDisable(true);
            sign.setVisible(true);
            signTitle.setVisible(true);
        }
        if (actionEvent.getSource().equals(sdk)) {
            secret.setText("");
            sign.setText("");
            sign.setVisible(false);
            signTitle.setVisible(false);
            SM.setDisable(false);
        }
    }

    public void submit(ActionEvent actionEvent) {
        String type;
        String text = in.getText();
        if (StringUtils.isEmpty(text)) {
            new Alert(Alert.AlertType.NONE, "输入不能为空！", new ButtonType[]{ButtonType.CLOSE}).show();
            return;
        }
        if (StringUtils.isEmpty(secret.getText())) {
            new Alert(Alert.AlertType.NONE, "秘钥不能为空！", new ButtonType[]{ButtonType.CLOSE}).show();
            return;
        }
        if (AES.isSelected()) {
            type = EncryptUtil.AES;
        } else {
            type = EncryptUtil.SMS;
        }
        if (sdk.isSelected()) {
            sign.setText(secret.getText());
        }
        String result = "";
        if (decode.isSelected()) {
            result = decodeData(type);
            saveData("解密", text, result);
        }
        if (encode.isSelected()) {
            result = encodeData(type);
            saveData("加密", text, result);
        }
        System.out.println(result);
        out.setText(result);
    }

    private String encodeData(String type) {
        String s = "";
        try {
            String text = in.getText();
            JSONObject in = new JSONObject();
            try {
                in = JSON.parseObject(text);
            } catch (Exception e) {
                in.put("data", text);
            }
            String sign = "";
            if (isSign.isSelected()) {
                String timestamp = in.getString("timestamp");
                if (StringUtils.isEmpty(timestamp)) {
                    timestamp = in.getString("createTime");
                }
                if (StringUtils.isEmpty(timestamp)) {
                    timestamp = System.currentTimeMillis() + "";
                }
                in.remove("timestamp");
                in.remove("createTime");
                in.remove("sign");
                if (sdk.isSelected()) {
                    try {
                        if (null == in.getJSONObject("data")) {
                            sign = EncryptUtil.getSDKV3Sign(in, this.sign.getText(), type, timestamp);
                        } else {
                            sign = EncryptUtil.getSDKV3Sign(in.getJSONObject("data"), this.sign.getText(), type, timestamp);
                        }
                    } catch (Exception e) {
                        sign = EncryptUtil.getSDKV3Sign(in, this.sign.getText(), type, timestamp);
                    }
                    in.put("timestamp", timestamp);
                }
                if (web.isSelected()) {
                    sign = EncryptUtil.getSDKV3Sign(in, this.sign.getText(), type, timestamp);
                    in.put("createTime", timestamp);
                }
                in.put("sign", sign);
                this.signResult.setText(sign);
            }
            s = EncryptUtil.encrypt(in.toJSONString(), this.secret.getText(), type);
        } catch (Exception e) {
            s = "加密失败！";
            this.signResult.setText("加签失败");
        }

        return s;
    }

    private String decodeData(String type) {
        String result = "";
        try {
            String text = in.getText();
            try {
                text = JSON.parseObject(text).getString("encryptScript");
            } catch (JSONException e) {
            }
            String decrypt = EncryptUtil.decrypt(text, secret.getText(), type);
            if (StringUtils.isEmpty(decrypt)) {
                throw new Exception("");
            }
            JSONObject json = JSON.parseObject(decrypt);
            if (isSign.isSelected()) {
                String sign = json.getString("sign");
                JSONObject signData = new JSONObject();
                json.remove("sign");
                String time = "";
                if (web.isSelected()) {
                    time = json.getString("createTime");
                    signData.putAll(json);
                    signData.remove("createTime");
                } else if (sdk.isSelected()) {
                    time = json.getString("timestamp");
                    try {
                        if (null == json.getJSONObject("data")) {
                            signData.putAll(json);
                        } else {
                            signData.putAll(json.getJSONObject("data"));
                        }
                    } catch (Exception e) {
                        signData.putAll(json);
                    }


                    signData.remove("timestamp");
                }
                if (!EncryptUtil.checkSDKV3Sign(signData, this.sign.getText(), sign, type, time)) {
                    signResult.setText("验签失败");
                } else {
                    signResult.setText("验签成功");
                }
                json.put("sign", sign);
            }
            String allData = json.getString("allData");
            if (StringUtils.isNotEmpty(allData)) {
                JSONObject tmp = JSON.parseObject(allData);
                json.put("allData", tmp);
            }
            String pretty = JSON.toJSONString(json, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
                    SerializerFeature.WriteDateUseDateFormat);
            result += pretty;
        } catch (Exception e) {
            result += "解密失败";
            if (isSign.isSelected()) {
                signResult.setText("验签失败");
            }
        }
        return result;
    }

    private void saveData(String type, String in, String out) {
        if ("解密".equals(type)) {
            out = JSON.parseObject(out).toJSONString();
        }
        File file = FileUtil.file(tmpFile);
        if (!file.exists()) {
            FileUtil.mkdir(file.getParent());
        }
        String content = type + split + this.secret.getText() + split + this.sign.getText() + split + in + split + out + split + DateUtil.format(DateUtil.date(), DatePattern.NORM_DATETIME_PATTERN);
        FileUtil.appendLines(Arrays.asList(content), file, Charset.defaultCharset());
    }

    public void project(ActionEvent actionEvent) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("project.fxml"));
        Scene scene = new Scene(root, -1, -1);
        Stage stage = new Stage();
        stage.setResizable(false);
        stage.setScene(scene);
        stage.show();
    }
}
